#include <ctype.h>
#include "random_cascade_classifier.h"

struct svm_problem prob;
struct svm_node *x_space;

#define Malloc(type,n) (type *)malloc((n)*sizeof(type))

void read_problem(const char *filename)
{
	int elements, max_index, i, j;
	fpos_t position;
	FILE *fp = fopen(filename,"r");
	
	if(fp == NULL)
	{
		fprintf(stderr,"can't open input file %s\n",filename);
		exit(1);
	}

	fgetpos (fp, &position);

	prob.l = 0;
	elements = 0;
	while(1)
	{
		int c = fgetc(fp);
		switch(c)
		{
			case '\n':
				++prob.l;
				// fall through,
				// count the '-1' element
			case ':':
				++elements;
				break;
			case EOF:
				goto out;
			default:
				;
		}
	}
out:
//	rewind(fp);
	fsetpos (fp, &position);

	prob.y = Malloc(double,prob.l);
	prob.x = Malloc(struct svm_node *,prob.l);
	x_space = Malloc(struct svm_node,elements);

	if(prob.y == NULL || prob.x == NULL || x_space == NULL) {
		double ynum = sizeof(double) * prob.l / (1024 * 1024.0);
		double xnum = sizeof(struct svm_node) * prob.l / (1024 * 1024.0);
		double spacenum = sizeof(struct svm_node) * elements / (1024 * 1024.0);
		fprintf(stderr,"Virtual Memory should be at least %f MB!\n", ynum + xnum + spacenum);
		exit(1);
	}

	max_index = 0;
	j=0;
	for(i=0;i<prob.l;i++)
	{
		double label;
		prob.x[i] = &x_space[j];
		fscanf(fp,"%lf",&label);
		prob.y[i] = label;

		while(1)
		{
			int c;
			do {
				c = getc(fp);
				if(c=='\n') goto out2;
			} while(isspace(c));
			ungetc(c,fp);
			if (fscanf(fp,"%d:%lf",&(x_space[j].index),&(x_space[j].value)) < 2)
			{
				fprintf(stderr,"last c is |%c|\n", c);
				fprintf(stderr,"Wrong input format at line %d\n", i+1);
				exit(1);
			}
			++j;
		}	
out2:
		if(j>=1 && x_space[j-1].index > max_index)
			max_index = x_space[j-1].index;
		x_space[j++].index = -1;
	}

	fclose(fp);
}

int main(int argc, char ** argv) {
	
	if(argc != 5) {
		return 1;
	}

	read_problem(argv[1]);
	int n_layer = atoi(argv[3]);
	double gamma = atof(argv[4]);
	

	RandomCascadeClassifier classifier;
	classifier.train(prob, 2000, n_layer, gamma);
	classifier.dump(argv[2]);

	free(prob.y);
	free(prob.x);
	free(x_space);

	return 0;
}